package com.beck.code.generator.generatorProcessor;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.beck.code.generator.configProperty.ContextConfig;
import com.beck.code.generator.configProperty.TableConfig;
import com.beck.code.generator.vo.DTOJavaCodeVO;
import com.beck.code.generator.vo.EntityFieldVO;
import jakarta.persistence.*;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author CuiJianbo
 * @since 2025/7/1
 */

public class DTOGenerator extends CommonGenerator {

    public DTOGenerator(TableConfig tableConfig, IntrospectedTable introspectedTable, ContextConfig contextConfig) {
        super(tableConfig, introspectedTable, contextConfig, contextConfig.getDtoGeneratorConfig());
    }

    public static DTOGenerator getInstance(TableConfig tableConfig, IntrospectedTable introspectedTable, ContextConfig contextConfig) {
        return new DTOGenerator(tableConfig, introspectedTable, contextConfig);
    }

    @Override
    void generateCodeFile() {
        String daoPackage = contextConfig.getDtoGeneratorConfig().getTargetPackage();
        DTOJavaCodeVO dtoJavaCodeVO = new DTOJavaCodeVO();
        BeanUtil.copyProperties(commonGeneratorVO, dtoJavaCodeVO);
        dtoJavaCodeVO.setPackageName(daoPackage);
        dtoJavaCodeVO.setEntityFields(getEntityFieldVOs());
        dtoJavaCodeVO.setImportJavaFullNames(getImportJavaFullNames());
        dtoJavaCodeVO.setServicePackageName(contextConfig.getServiceGeneratorConfig().getTargetPackage());

        //填充模板文件
        String data = applyTemplateResources(contextConfig.getDtoGeneratorConfig().getTemplate(), dtoJavaCodeVO);

        //输出真实文件
        boolean flag = generateCodeFile(data);

        if (flag) {
            System.out.println(fileName());
        }
    }

    private List<EntityFieldVO> getEntityFieldVOs() {
        Class entityClass = null;
        try {
            entityClass = ClassLoader.getSystemClassLoader().loadClass(entityFullName);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
        return Arrays.stream(entityClass.getDeclaredFields())
                .map(EntityFieldVO::getEntityFieldVO)
                .collect(Collectors.toList());
    }

    private List<String> getImportJavaFullNames() {
        Class entityClass = null;
        try {
            entityClass = ClassLoader.getSystemClassLoader().loadClass(entityFullName);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
        Field[] fieldsList = entityClass.getDeclaredFields();
        List<String> stringList = new ArrayList<>();
        boolean hasList = false;
        boolean hasDate = false;
        for (Field p : fieldsList) {
            if (p.getAnnotation(ManyToMany.class) != null || p.getAnnotation(OneToMany.class) != null) {
                stringList.add(((ParameterizedType) p.getGenericType()).getActualTypeArguments()[0].getTypeName());
                hasList = true;
            } else if (p.getAnnotation(ManyToOne.class) != null || p.getAnnotation(OneToOne.class) != null) {
                stringList.add(p.getType().getName());
            }

            if (p.getType().equals(Date.class)) {
                hasDate = true;
            }
        }
        if (hasList) {
            stringList.add("java.util.List");
        }
        if (hasDate) {
            stringList.add("java.util.Date");
        }
        return stringList;
    }

    @Override
    String fileName() {
        String fileName = StrUtil.concat(true, StrUtil.upperFirst(entityName), "DTO.java");
        return contextConfig.getDtoGeneratorConfig().getTargetPackage().replace(".", "/") + "/" + fileName;
    }


}


